package org.movee.spring.data.hugegraph.repository.query;

import org.movee.spring.data.hugegraph.annotation.Query;
import org.movee.spring.data.hugegraph.gremlin.GremlinTraversal;
import org.movee.spring.data.hugegraph.query.HugeOperations;
import org.movee.spring.data.hugegraph.query.paramerter.HugeParameterAccessor;
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
import org.springframework.expression.spel.standard.SpelExpressionParser;

public class StringBasedHugeRepositoryQuery extends AbstractHugeRepositoryQuery {

    private static final String COUNT_AND_EXISTS = "Manually defined query for %s cannot be a count " +
            "and exists query at the same time!";


    private final StringBasedQuery stringBasedQuery;

    private final boolean isCountQuery;

    private final boolean isExistsQuery;

    public StringBasedHugeRepositoryQuery(HugeQueryMethod queryMethod,
                                          HugeOperations operations,
                                          SpelExpressionParser expressionParser,
                                          QueryMethodEvaluationContextProvider evaluationContextProvider) {

        this(queryMethod.getRequiredAnnotatedQuery(), queryMethod, operations,
                expressionParser, evaluationContextProvider);
    }

    public StringBasedHugeRepositoryQuery(String query,
                                          HugeQueryMethod method,
                                          HugeOperations operations,
                                          SpelExpressionParser expressionParser,
                                          QueryMethodEvaluationContextProvider evaluationContextProvider) {

        super(method, operations);

        this.stringBasedQuery = new StringBasedQuery(query,
                new ExpressionEvaluatingParameterBinder(expressionParser, evaluationContextProvider));

        if (method.hasAnnotatedQuery()) {

            Query queryAnnotation = method.getQueryAnnotation().orElse(null);

            this.isCountQuery = queryAnnotation.count();
            this.isExistsQuery = queryAnnotation.exists();

            if (this.isCountQuery && this.isExistsQuery) {
                throw new IllegalArgumentException(String.format(COUNT_AND_EXISTS, method));
            }
        } else {
            this.isCountQuery = false;
            this.isExistsQuery = false;
        }
    }

    protected StringBasedQuery getStringBasedQuery() {
        return this.stringBasedQuery;
    }

    @Override
    public GremlinTraversal createQuery(HugeParameterAccessor parameterAccessor) {
        return getQueryHugeTraversalCreator().traversal(getStringBasedQuery(), parameterAccessor);
    }

}
